/*
 * Copyright (C) 2014 Steven Kurilovitch
 *
 * This program is free software: you can redistribute it and/or modify
 * it under the terms of the GNU General Public License as published by
 * the Free Software Foundation, either version 3 of the License, or
 * (at your option) any later version.
 *
 * This program is distributed in the hope that it will be useful,
 * but WITHOUT ANY WARRANTY; without even the implied warranty of
 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
 * GNU General Public License for more details.
 *
 * You should have received a copy of the GNU General Public License
 * along with this program.  If not, see <http://www.gnu.org/licenses/>.
 */

package com.goodjaerb.swccg.ui;

import com.goodjaerb.swccg.core.CardData;
import com.goodjaerb.swccg.core.filter.Filter;
import java.awt.Image;
import java.awt.event.AdjustmentEvent;
import java.io.IOException;
import java.util.ArrayList;
import java.util.Collections;
import java.util.List;
import java.util.logging.Level;
import java.util.logging.Logger;

/**
 *
 * @author Steven Kurilovitch
 */
public class CardSheet extends javax.swing.JPanel {

    private List<CardData> masterList;
    private List<CardData> filteredList;
    private final CardPanel[] cards;
    private int currentPage;
    
    /**
     * Creates new form CardSheet
     */
    public CardSheet() {
        super();
        initComponents();
        
        masterList = new ArrayList<>();
        
        cards = new CardPanel[] {
            cardPanel1,
            cardPanel2,
            cardPanel3,
            cardPanel4,
            cardPanel5,
            cardPanel6,
            cardPanel7,
            cardPanel8,
            cardPanel9,
            cardPanel10
        };
    }
    
    public void filter(List<Filter> filters) {
        filteredList.clear();
        masterList.stream().forEach((cd) -> {
            boolean pass = true;
            for(Filter f : filters) {
                if(!f.passes(cd)) {
                    pass = false;
                }
            }
            if(pass) {
                filteredList.add(cd);
            }
        });
    }
    
    public CardData getCard(String cardPath) {
        for(CardData cd : masterList) {
            if(cd.get(CardData.Field.HOLOTABLE_CARD_PATH).equals(cardPath) ||
                    cd.get(CardData.Field.HOLOTABLE_CARD_PATH).replace("/legacy/", "/starwars/").equals(cardPath)) {
                return cd;
            }
        }
        return null;
    }
    
    public CardPanel getNextPanelInDirection(CardPanel fromPanel, int direction) throws IOException {
        int newIndex = filteredList.indexOf(fromPanel.getCard()) + direction;
        if(newIndex >= 0 && newIndex < filteredList.size()) {
            if(newIndex < 10 * currentPage - 10 || newIndex >= 10 * currentPage) {
                //change page.
                setCardPage(currentPage + direction);
            }
            return cards[newIndex - ((currentPage - 1) * 10)];
        }
        // out of bounds, return the previous used card.
        newIndex = newIndex - ((currentPage - 1) * 10) - direction;
        if(newIndex < 0) {
            // still out of bounds, go to 0.
            newIndex = 0;
        }
        return cards[newIndex];
    }
    
    public CardData getCardAtIndex(int index) {
        return cards[index].getCard();
    }
    
    public Image getImageAtIndex(int index) {
        return cards[index].getImage();
    }
    
    public void clearSheet() throws IOException {
        for(CardPanel cp : cards) {
            cp.setCard(null);
        }
        masterList = new ArrayList<>();
        filteredList = null;
        repaint();
    }
    
    public void addCard(CardData cd) {
        masterList.add(cd);
        if(cd.isTwoSided()) {
            masterList.add(cd.getAsBack());
        }
    }
    
    public void rescaleCards() {
        for(CardPanel cp : cards) {
            cp.rescale();
        }
    }
    
    public void turnPage(int x) {
        cardPageScroll.setValue(currentPage + x);
    }
    
    public void resetSheet() throws IOException {
        if(filteredList == null) {
            filteredList = new ArrayList<>(masterList);
        }
        Collections.sort(filteredList);
        
        cardPageScroll.setMinimum(1);
        cardPageScroll.setMaximum((int)Math.ceil(filteredList.size() / 10.));
        cardPageScroll.setVisibleAmount(0);
        if(cardPageScroll.getValue() == 1) {
            // if already at page one, the event handler won't fire to call setcardpage, so do it myself.
            setCardPage(1);
        }
        else {
            // this will call setcardpage from the event handler.
            cardPageScroll.setValue(1);
        }
    }
    
    private void setCardPage(int p) throws IOException {
        if(filteredList == null || filteredList.isEmpty()) {
            for(CardPanel cp : cards) {
                cp.setCard(null);
            }
            currentPage = 1;
            repaint();
        }
        else if(p > 0 && p <= (int)Math.ceil(filteredList.size() / 10.)) {
            boolean backSideNext = false;
            for(int i = 0; i < 10; i++) {
                try {
                    CardData card = filteredList.get(i + (10 * p) - 10);
                    if(card.isTwoSided()) {
                        if(backSideNext) {
                            cards[i].setCard(card, backSideNext);
                            backSideNext = false;
                        }
                        else {
                            cards[i].setCard(card);
                            backSideNext = true;
                        }
                    }
                    else {
                        cards[i].setCard(card);
                    }
                }
                catch(IndexOutOfBoundsException e) {
                    cards[i].setCard(null);
                }
            }
            currentPage = p;
            repaint();
        }
    }

    /**
     * This method is called from within the constructor to initialize the form.
     * WARNING: Do NOT modify this code. The content of this method is always
     * regenerated by the Form Editor.
     */
    @SuppressWarnings("unchecked")
    // <editor-fold defaultstate="collapsed" desc="Generated Code">//GEN-BEGIN:initComponents
    private void initComponents() {

        cardPageScroll = new javax.swing.JScrollBar();
        cardPanel2 = new com.goodjaerb.swccg.ui.CardPanel();
        cardPanel3 = new com.goodjaerb.swccg.ui.CardPanel();
        cardPanel4 = new com.goodjaerb.swccg.ui.CardPanel();
        cardPanel5 = new com.goodjaerb.swccg.ui.CardPanel();
        cardPanel6 = new com.goodjaerb.swccg.ui.CardPanel();
        cardPanel7 = new com.goodjaerb.swccg.ui.CardPanel();
        cardPanel8 = new com.goodjaerb.swccg.ui.CardPanel();
        cardPanel9 = new com.goodjaerb.swccg.ui.CardPanel();
        cardPanel10 = new com.goodjaerb.swccg.ui.CardPanel();
        cardPanel1 = new com.goodjaerb.swccg.ui.CardPanel();

        addComponentListener(new java.awt.event.ComponentAdapter() {
            public void componentResized(java.awt.event.ComponentEvent evt) {
                formComponentResized(evt);
            }
        });

        cardPageScroll.setOrientation(javax.swing.JScrollBar.HORIZONTAL);
        cardPageScroll.addAdjustmentListener(new java.awt.event.AdjustmentListener() {
            public void adjustmentValueChanged(java.awt.event.AdjustmentEvent evt) {
                cardPageScrollAdjustmentValueChanged(evt);
            }
        });

        javax.swing.GroupLayout layout = new javax.swing.GroupLayout(this);
        this.setLayout(layout);
        layout.setHorizontalGroup(
            layout.createParallelGroup(javax.swing.GroupLayout.Alignment.LEADING)
            .addGroup(layout.createSequentialGroup()
                .addContainerGap()
                .addGroup(layout.createParallelGroup(javax.swing.GroupLayout.Alignment.LEADING)
                    .addGroup(layout.createSequentialGroup()
                        .addComponent(cardPanel1, javax.swing.GroupLayout.DEFAULT_SIZE, 196, Short.MAX_VALUE)
                        .addGap(10, 10, 10)
                        .addComponent(cardPanel2, javax.swing.GroupLayout.DEFAULT_SIZE, 196, Short.MAX_VALUE)
                        .addPreferredGap(javax.swing.LayoutStyle.ComponentPlacement.UNRELATED)
                        .addComponent(cardPanel3, javax.swing.GroupLayout.DEFAULT_SIZE, 196, Short.MAX_VALUE)
                        .addPreferredGap(javax.swing.LayoutStyle.ComponentPlacement.UNRELATED)
                        .addComponent(cardPanel4, javax.swing.GroupLayout.DEFAULT_SIZE, 196, Short.MAX_VALUE)
                        .addPreferredGap(javax.swing.LayoutStyle.ComponentPlacement.UNRELATED)
                        .addComponent(cardPanel5, javax.swing.GroupLayout.DEFAULT_SIZE, 196, Short.MAX_VALUE))
                    .addGroup(layout.createSequentialGroup()
                        .addComponent(cardPanel6, javax.swing.GroupLayout.DEFAULT_SIZE, 196, Short.MAX_VALUE)
                        .addPreferredGap(javax.swing.LayoutStyle.ComponentPlacement.UNRELATED)
                        .addComponent(cardPanel7, javax.swing.GroupLayout.DEFAULT_SIZE, 196, Short.MAX_VALUE)
                        .addPreferredGap(javax.swing.LayoutStyle.ComponentPlacement.UNRELATED)
                        .addComponent(cardPanel8, javax.swing.GroupLayout.DEFAULT_SIZE, 196, Short.MAX_VALUE)
                        .addPreferredGap(javax.swing.LayoutStyle.ComponentPlacement.UNRELATED)
                        .addComponent(cardPanel9, javax.swing.GroupLayout.DEFAULT_SIZE, 196, Short.MAX_VALUE)
                        .addPreferredGap(javax.swing.LayoutStyle.ComponentPlacement.UNRELATED)
                        .addComponent(cardPanel10, javax.swing.GroupLayout.DEFAULT_SIZE, 196, Short.MAX_VALUE))
                    .addComponent(cardPageScroll, javax.swing.GroupLayout.DEFAULT_SIZE, javax.swing.GroupLayout.DEFAULT_SIZE, Short.MAX_VALUE))
                .addContainerGap())
        );
        layout.setVerticalGroup(
            layout.createParallelGroup(javax.swing.GroupLayout.Alignment.LEADING)
            .addGroup(javax.swing.GroupLayout.Alignment.TRAILING, layout.createSequentialGroup()
                .addGroup(layout.createParallelGroup(javax.swing.GroupLayout.Alignment.LEADING)
                    .addComponent(cardPanel2, javax.swing.GroupLayout.DEFAULT_SIZE, javax.swing.GroupLayout.DEFAULT_SIZE, Short.MAX_VALUE)
                    .addComponent(cardPanel3, javax.swing.GroupLayout.DEFAULT_SIZE, javax.swing.GroupLayout.DEFAULT_SIZE, Short.MAX_VALUE)
                    .addComponent(cardPanel4, javax.swing.GroupLayout.DEFAULT_SIZE, javax.swing.GroupLayout.DEFAULT_SIZE, Short.MAX_VALUE)
                    .addComponent(cardPanel5, javax.swing.GroupLayout.DEFAULT_SIZE, javax.swing.GroupLayout.DEFAULT_SIZE, Short.MAX_VALUE)
                    .addComponent(cardPanel1, javax.swing.GroupLayout.DEFAULT_SIZE, javax.swing.GroupLayout.DEFAULT_SIZE, Short.MAX_VALUE))
                .addPreferredGap(javax.swing.LayoutStyle.ComponentPlacement.RELATED)
                .addGroup(layout.createParallelGroup(javax.swing.GroupLayout.Alignment.TRAILING)
                    .addComponent(cardPanel8, javax.swing.GroupLayout.Alignment.LEADING, javax.swing.GroupLayout.DEFAULT_SIZE, javax.swing.GroupLayout.DEFAULT_SIZE, Short.MAX_VALUE)
                    .addComponent(cardPanel9, javax.swing.GroupLayout.Alignment.LEADING, javax.swing.GroupLayout.DEFAULT_SIZE, javax.swing.GroupLayout.DEFAULT_SIZE, Short.MAX_VALUE)
                    .addComponent(cardPanel10, javax.swing.GroupLayout.Alignment.LEADING, javax.swing.GroupLayout.DEFAULT_SIZE, javax.swing.GroupLayout.DEFAULT_SIZE, Short.MAX_VALUE)
                    .addComponent(cardPanel7, javax.swing.GroupLayout.DEFAULT_SIZE, javax.swing.GroupLayout.DEFAULT_SIZE, Short.MAX_VALUE)
                    .addComponent(cardPanel6, javax.swing.GroupLayout.Alignment.LEADING, javax.swing.GroupLayout.DEFAULT_SIZE, javax.swing.GroupLayout.DEFAULT_SIZE, Short.MAX_VALUE))
                .addPreferredGap(javax.swing.LayoutStyle.ComponentPlacement.RELATED)
                .addComponent(cardPageScroll, javax.swing.GroupLayout.PREFERRED_SIZE, javax.swing.GroupLayout.DEFAULT_SIZE, javax.swing.GroupLayout.PREFERRED_SIZE))
        );
    }// </editor-fold>//GEN-END:initComponents

    private void cardPageScrollAdjustmentValueChanged(java.awt.event.AdjustmentEvent evt) {//GEN-FIRST:event_cardPageScrollAdjustmentValueChanged
        if(evt.getAdjustmentType() == AdjustmentEvent.TRACK) {
            try {
                setCardPage(evt.getValue());
            } catch (IOException ex) {
                Logger.getLogger(CardSheet.class.getName()).log(Level.SEVERE, null, ex);
            }
        }
    }//GEN-LAST:event_cardPageScrollAdjustmentValueChanged

    private void formComponentResized(java.awt.event.ComponentEvent evt) {//GEN-FIRST:event_formComponentResized
//        rescaleCards();
    }//GEN-LAST:event_formComponentResized
    
    // Variables declaration - do not modify//GEN-BEGIN:variables
    private javax.swing.JScrollBar cardPageScroll;
    private com.goodjaerb.swccg.ui.CardPanel cardPanel1;
    private com.goodjaerb.swccg.ui.CardPanel cardPanel10;
    private com.goodjaerb.swccg.ui.CardPanel cardPanel2;
    private com.goodjaerb.swccg.ui.CardPanel cardPanel3;
    private com.goodjaerb.swccg.ui.CardPanel cardPanel4;
    private com.goodjaerb.swccg.ui.CardPanel cardPanel5;
    private com.goodjaerb.swccg.ui.CardPanel cardPanel6;
    private com.goodjaerb.swccg.ui.CardPanel cardPanel7;
    private com.goodjaerb.swccg.ui.CardPanel cardPanel8;
    private com.goodjaerb.swccg.ui.CardPanel cardPanel9;
    // End of variables declaration//GEN-END:variables
}
